"""
CPM/Console: Определние вспомогательныъ классов для взаимодействия с Консолью
Author: <ilinuri Nirvalen
Ver: 2.0
"""

from config import Config


class Context:
    """Вспомогательный передаваемый в функции класс.

    :param args: Аргументы (цели) команды
    :param flags: Флаги работы команды"""

    def __init__(self, args=[], flags={}):
        self.args = args
        self.flags = flags

        # Дополнительное представление списка аргументов
        self.largs = ', '.join(map(str, args))
        self.sargs = ' '.join(map(str, args))

    def __iter__(self):
        for a in self.args:
            yield a

    def get_flag(self, key, value=None):
        return self.flags.get(key, value)

    def is_flags(self, flags, value=True):
        for x in flags:
            if not self.get_flag(x, value):
                return False

        return True


class Console:
    """Небольшой класс для создания консольного приложения.
    Когда-нибудь будет заменён..."""

    def __init__(self):
        super(Console, self).__init__()
        self.commands = {}

        self.add_command(self.commands_help, "help", 
                         usage='Cписок команд с их описанием')
       

    # Вспомогательные методы
    # ======================

    def add_command(self, func, name, usage, flags={}):
        """Добавляет новый обработчик команды.

        :param func: Функция обработчика команды
        :param name: Имя для обработчика (команды)
        :param usage: Описание что делает команда
        :param flags: Флаги по умолчанию для команды"""

        self.commands[name] = {'func':func, 'usage':usage, 'flags':flags}        

    def process(self, args):
        """Обрабатывает входящие аргументы.
        
        :param args: Аргументы для обработки"""

        command = ''
        cargs = []
        flags = {}
        router = {}

        # распределение входных аргументов на ключи и аргументы команды
        for x in args:
            if x[0] == '-':
                x = x.strip('-').split('=', 1)

                if len(x) == 1:
                    flags[x[0]] = True
                
                elif x[1].isdigit():
                    flags[x[0]] = int(x[1])
                
                elif x[1].lower() == 'false':
                    flags[x[0]] = False
                
                else:
                    flags[x[0]] = x[1]

            else:
                cargs.append(x)

        # получаем название команды
        if len(cargs) >= 1:
            command = cargs.pop(0)

        if command in self.commands:
            router = self.commands[command]

            router["flags"].update(flags)
            ctx = Context(cargs, router["flags"])
            router["func"](ctx)

        elif command == '':
            self.commands_help(Context())
        else:
            print(f'"{command}" не является командой, "help" для вывода справки.')


    # Описание базовых команд
    # =======================

    def commands_help(self, ctx):
        """[команда] Выводит список всех команд с описанием."""

        print(f'Использование: *.py [Flags] [Command] [Targets]')
        print('-'*60)
        print(f'  Flags: Параметры для каоманды')
        print(f'  Command: Команда для выполнения')
        print(f'  Targets: Цели для выполнения командой')
        print()

        s = max(map(len, self.commands))

        for k, v in self.commands.items():
            
            flags = []
            usage = v["usage"]

            for flag, default in v["flags"].items():
                flags.append(f'--{flag}= {default}')

            """
            if v['u'].count('[') == 1 and v['u'].count(']') == 1:
                x = v['u'][1:].split(']', 1)
                text = x[1]
                for k in x[0].split(';'):
                    keys.append(k.strip())
            else:
                text = v['u']
            """

            if flags:
                flags_str = f" \033[90m{' '.join(flags)}\033[0m"
            else:
                flags_str = ""

            if flags_str:
                print(f'  \033[94m{k}\033[0m{flags_str}')
                print(f'    {usage}')
            else:
                print(f'  \033[94m{k}\033[0m: {flags_str}{usage}')
            
